using System;
using System.Collections.Generic;
using Hammock.Web;
using WWB.DisqusSharp.Infrastructure.Disqus;
using WWB.DisqusSharp.Infrastructure.HammockWrappers;
using WWB.DisqusSharp.Model.DisqusDTO;
using WWB.DisqusSharp.Model.DisqusService;
using Hammock;

namespace WWB.DisqusSharp.Infrastructure.HammockWrappers
{
    public class HammockDisqusService : HammockServiceBase, IDisqusService 
    {
        private readonly string apiKey;

        private RestClient theClient;
        private readonly JsonDotNetSerializer serializer = new JsonDotNetSerializer();

        public HammockDisqusService(string apiKey)
        {
            if (string.IsNullOrEmpty(apiKey)) throw new ArgumentNullException("apiKey");
            this.apiKey = apiKey;
        }

        protected override RestClient GetRestClient()
        {
            if (theClient == null)
            {
                theClient = new RestClient()
                {
                    Authority = DisqusSharpCurrentVersion.Authority,
                };
                theClient.AddParameter("user_api_key", apiKey);
                theClient.AddParameter("api_version", DisqusSharpCurrentVersion.ApiVersion);
                theClient.UserAgent = DisqusSharpCurrentVersion.UserAgent;
                theClient.Serializer = serializer;
                theClient.Deserializer = serializer;
            }
            return theClient;
        }


        #region Implementation of IDisqusService

        public IDisqusServiceResult<string> GetUserName()
        {
            var r = new RestRequest()
                        {
                            Path = Endpoints.GetUserName,
                            Method = WebMethod.Post
                        };
            return ExecuteRequest<string>(r);
        }

        public IDisqusServiceResult<string> GetForumApiKey(string forum_id)
        {
            var r = new RestRequest()
                        {
                            Path = Endpoints.GetForumApiKey
                        }
                .WithParameter("forum_id", forum_id);
            return ExecuteRequest<string>(r);
        }

        public IDisqusForumService GetForumApi(string forum_id)
        {
            var fresp = GetForumApiKey(forum_id);
            if (fresp.IsError)
            {
                throw new DisqusServiceException("fatal", string.Format("Cannot create api key for forum ID {0}. Error was {1}.", forum_id, fresp.Error));
            }
            HammockDisqusForumService hdfs = new HammockDisqusForumService(apiKey, fresp.Payload, forum_id);
            return hdfs;
        }

        public IDisqusServiceResult<IEnumerable<Forum>> GetForumList()
        {
            var r = new RestRequest()
                        {
                            Path = Endpoints.GetForumList
                        };
            return ExecuteRequest<IEnumerable<Forum>>(r);
        }

        public  IDisqusServiceResult<IEnumerable<ThreadPost>> GetForumPosts(string forum_id)
        {
            var r = new RestRequest()
                        {
                            Path = Endpoints.GetForumPosts
                        }
                .WithParameter("forum_id", forum_id);
            return ExecuteRequest<IEnumerable<ThreadPost>>(r);
        }

        public IDisqusServiceResult<ForumPostCount> GetNumPosts(IEnumerable<string> threadIds)
        {
            var r = new RestRequest()
                        {
                            Path = Endpoints.GetNumPosts
                        }
                .WithMultiValueStringParameter("thread_ids", threadIds);
            return ExecuteRequest<ForumPostCount>(r);
        }


        public IDisqusServiceResult<IEnumerable<Category>> GetCategoriesList(string forum_id)
        {
            var r = new RestRequest()
                        {
                            Path = Endpoints.GetCategoriesList
                        }
                .ForForum(forum_id);
            return ExecuteRequest<IEnumerable<Category>>(r);
        }

        public IDisqusServiceResult<IEnumerable<DisqusFullBodyThread>> GetThreadList(string forum_id, StartLimitArgs args)
        {
            var r = new RestRequest()
                        {Path = Endpoints.GetThreadList}
                .ForForum(forum_id)
                .StartingAtAndLimiting(args);
            return ExecuteRequest<IEnumerable<DisqusFullBodyThread>>(r);
        }


        public IDisqusServiceResult<IEnumerable<DisqusCategoryIdThread>> GetUpdatedThreads(string forum_id, DateTime since)
        {
            var r = new RestRequest() {Path = Endpoints.GetUpdatedThreads}
                .ForForum(forum_id)
                .WithParameter("since", since.ToString("yyyy'-'MM'-'dd'T'HH':'mm"));
            return ExecuteRequest<IEnumerable<DisqusCategoryIdThread>>(r);
        }

        public IDisqusServiceResult<IEnumerable<ThreadPost>> GetThreadPosts(string thread_id)
        {
            return GetThreadPosts(thread_id, new GetPostArgs());
        }

        public IDisqusServiceResult<IEnumerable<ThreadPost>> GetThreadPosts(string thread_id, GetPostArgs args)
        {
            var r = new RestRequest() {Path = Endpoints.GetThreadPosts}
                .ForThread(thread_id)
                .StartingAtAndLimiting(args)
                .WithMultiValueStringParameter("filter", args.Filters)
                .WithMultiValueStringParameter("exclude", args.Exclude);
            return ExecuteRequest<IEnumerable<ThreadPost>>(r);
        }

        #endregion
    }
}
